#include "camerawidget.h"

CameraWidget::CameraWidget(QWidget *parent) : QMainWindow(parent)
{
    isOpen = false;

    // 1.菜单
    QMenuBar *menu_bar = this->menuBar(); // 获取原本的空白菜单
    menu = menu_bar->addMenu("设备");
    menu->setEnabled(false);

    // 2.中心组件
    QWidget *central = new QWidget;
    this->setCentralWidget(central);

    // 3.主布局
    QHBoxLayout *mlayout = new QHBoxLayout(central);

    // 4.左边，预览窗口
    // 4.1 子布局1
    left_layout = new QVBoxLayout;
    // 4.2 设置凸起边框效果的容器
    raised_frame = new QFrame;
    raised_frame->setFrameStyle(QFrame::Panel | QFrame::Raised); // 凸起边框效果
    raised_frame->setLineWidth(3); // 边框粗细
    // 4.3 将承载预览的视频流与容器绑定
    finder = new QCameraViewfinder(raised_frame);
    finder->setFixedSize(raised_frame->width() - 1, raised_frame->height() - 1);
    // 4.4 将组件与布局绑定
    left_layout->addWidget(new QLabel("监  控: "), 0);
    left_layout->addWidget(raised_frame, 1);
    mlayout->addLayout(left_layout);

    // 5.右边
    // 5.1 子布局2
    QVBoxLayout *right_layout = new QVBoxLayout;
    // 5.2 上部，截图
    QFrame *plain_frame = new QFrame; // 承载截图的标签组件的容器
    plain_frame->setFrameStyle(QFrame::Box | QFrame::Plain); // 普通边框效果
    plain_frame->setLineWidth(3);
    capture_label = new QLabel(plain_frame); // 承载截图的标签组件
    capture_label->setFixedSize(plain_frame->width() - 1, plain_frame->height() - 1);
    // 5.3 按键
    capture_btn = new QPushButton("拍  照");
    capture_btn->setEnabled(false);
    open_btn = new QPushButton("开  启");
    // 5.4 添加到布局
    right_layout->addWidget(new QLabel("截  图: "), 0);
    right_layout->addWidget(plain_frame, 1);
    right_layout->addWidget(capture_btn, 0);
    right_layout->addWidget(open_btn, 0);
    mlayout->addLayout(right_layout);

    // 6.摄像头
    // 6.1 将摄像头和截图器的指针归零，防止野指针
    camera = nullptr;
    capture = nullptr;
    // 6.2 获取摄像头列表
    QList<QCameraInfo> cameras_info = QCameraInfo::availableCameras();
    // 6.3 准备一个动作组
    QActionGroup *action_group = new QActionGroup(this);
    // 6.4 每个摄像头生成一个action，并添加到组中
    for(QCameraInfo camera_info : cameras_info)
    {
        QAction *action = new QAction(camera_info.description()); // 用户观察的设备名
        action->setData(camera_info.deviceName()); // 实际使用的设备名
        action->setCheckable(true); // 菜单带有选择效果
        action_group->addAction(action);
    }
    // 6.5 将整个组添加到menu中
    menu->addActions(action_group->actions());

    // 7.创建服务器
    tcpServer = tcpServerSingleton::create_tcpServer();

    // 8.信号/槽函数
    // 8.1 获取服务器信号
    this->connect(tcpServer, &tcpServerSingleton::sig_recv, this, [this](const QString recv){
        if(recv == "300")
        {
            menu->setEnabled(false);
            capture_btn->setEnabled(false);
            open_btn->setText("开  启");
            if(camera)
            {
                // 断开所有连接防止残留信号
                disconnect(camera, nullptr, this, nullptr);
                disconnect(capture, nullptr, this, nullptr);
                disconnect(finder, nullptr, this, nullptr);

                camera->stop();
                // 使用deletelater()交由QApplication删除，比手动delete更符合qt的逻辑
                camera->deleteLater();
                camera = nullptr;

                capture->deleteLater();
                capture = nullptr;
            }
            isOpen = false;
        }
        else if(recv == "301")
        {
            menu->setEnabled(true);
            capture_btn->setEnabled(true);
            open_btn->setText("关  闭");
            isOpen = true;
        }

        update();
    });

    // 8.2 点击“开启”按钮
    this->connect(open_btn, &QPushButton::clicked, this, [this](){
       if(isOpen)
       {
           open_btn->setText("开  启");
           menu->setEnabled(false);
           capture_btn->setEnabled(false);
           if(camera)
           {
               // 断开所有连接防止残留信号
               disconnect(camera, nullptr, this, nullptr);
               disconnect(capture, nullptr, this, nullptr);
               disconnect(finder, nullptr, this, nullptr);

               camera->stop();
               // 使用deletelater()交由QApplication删除，比手动delete更符合qt的逻辑
               camera->deleteLater();
               camera = nullptr;

               capture->deleteLater();
               capture = nullptr;
           }
           emit sig_send("300000");
           isOpen = !isOpen;
       }
       else
       {
           open_btn->setText("关  闭");
           menu->setEnabled(true);
           capture_btn->setEnabled(true);
           emit sig_send("301000");
           isOpen = !isOpen;
       }
    });

    // 8.3 点击菜单action，选择摄像头
    this->connect(action_group, &QActionGroup::triggered, this, &CameraWidget::slot_camera_selected);
    // 8.4 点击“拍照”按钮
    this->connect(capture_btn, &QPushButton::clicked, this, &CameraWidget::slot_camera_capture);
}

void CameraWidget::slot_camera_selected(QAction *action)
{
    if(camera)
    {
        // 断开所有连接防止残留信号
        disconnect(camera, nullptr, this, nullptr);
        disconnect(capture, nullptr, this, nullptr);
        disconnect(finder, nullptr, this, nullptr);

        camera->stop();
        // 使用deletelater()交由QApplication删除，比手动delete更符合qt的逻辑
        camera->deleteLater();
        camera = nullptr;

        capture->deleteLater();
        capture = nullptr;
    }

    // 1.利用data内的设备名打开摄像头
    camera = new QCamera(action->data().toByteArray());

    // 2.绑定摄像头的输出为viewfinder
    camera->setViewfinder(finder);

    // 3.截图器，绑定摄像头
    capture = new QCameraImageCapture(camera);

    // 4.截图器需要配置
    // 4.1 保存路径，未设置及默认路径
    // capture->setCaptureDestination(QCameraImageCapture::CaptureToFile | QCameraImageCapture::CaptureToBuffer);
    // 4.2 截图成功后的信号
    this->connect(capture, &QCameraImageCapture::imageCaptured, this, &CameraWidget::slot_image_captured);

    // 5.开启摄像头
    camera->start();

    // 6.发送信号给服务器
    emit sig_send("302000");
}
void CameraWidget::slot_camera_capture()
{
    // 判断camera可用才进行截图
    if(camera)
        capture->capture();

    emit sig_send("303000");
}
void CameraWidget::slot_image_captured(int index, const QImage &image)
{
    // 将image刷到QLabel上
    // 参数1为调节大小，参数2为保持原来比例，参数3为平滑效果
    QImage scaled_image = image.scaled(finder->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
    capture_label->setPixmap(QPixmap::fromImage(scaled_image));
    capture_label->setAlignment(Qt::AlignCenter); // 设置居中
}
